/*
 * ====================================================================
 * Copyright (c) 2004-2008 TMate Software Ltd.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://svnkit.com/license.html
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 * ====================================================================
 */
package ar.edu.sccs.util.svn;

import java.io.ByteArrayOutputStream;

import org.apache.log4j.Logger;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNProperty;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

import ar.edu.sccs.monitoring.logging.SCCSLogger;

/*
 * This example shows how to fetch a file and its properties from the repository
 * at the latest (HEAD) revision . If the file is a text (either it has no
 * svn:mime-type property at all or if has and the property value is text/-like)
 * its contents as well as properties will be displayed in the console,
 * otherwise - only properties. 
 * As an example here's a part of one of the
 * program layouts (for the default url and file path used in the program):
 *  
 * File property: svn:entry:revision=2802
 * File property: svn:entry:checksum=435f2f0d33d12907ddb6dfd611825ec9
 * File property: svn:wc:ra_dav:version-url=/repos/svnkit/!svn/ver/2795/trunk/www/license.html
 * File property: svn:entry:last-author=alex
 * File property: svn:entry:committed-date=2006-11-13T21:34:27.908657Z
 * File property: svn:entry:committed-rev=2795
 * File contents:
 * 
 * <html>
 * <head>
 * <link rel="shortcut icon" href="img/favicon.ico"/>
 * <title>SVNKit&nbsp;::&nbsp;License</title>
 * </head>
 * <body>
 * <h1>The TMate Open Source License.</h1>
 * <pre>
 * ......................................
 * ---------------------------------------------
 * Repository latest revision: 2802
 */
public class DisplayFile {

	static Logger logger = SCCSLogger.getLogger(DisplayFile.class);

	/*
	 * args parameter is used to obtain a repository location URL, user's
	 * account name & password to authenticate him to the server, the file path
	 * in the rpository (the file path should be relative to the the
	 * path/to/repository part of the repository location URL).
	 */
	public static String displayFile(String url, String filePath, String name, String password) {
		/*
		 * Default values:
		 */
//		String url = "http://svn.svnkit.com/repos/svnkit/trunk";
//		String name = "anonymous";
//		String password = "anonymous";
//		String filePath = "www/license.html";
		/*
		 * Initializes the library (it must be done before ever using the
		 * library itself)
		 */
		setupLibrary();

//		if (args != null) {
//			/*
//			 * Obtains a repository location URL
//			 */
//			url = (args.length >= 1) ? args[0] : url;
//			/*
//			 * Obtains a file path
//			 */
//			filePath = (args.length >= 2) ? args[1] : filePath;
//			/*
//			 * Obtains an account name (will be used to authenticate the user to
//			 * the server)
//			 */
//			name = (args.length >= 3) ? args[2] : name;
//			/*
//			 * Obtains a password
//			 */
//			password = (args.length >= 4) ? args[3] : password;
//		}
		SVNRepository repository = null;
		try {
			/*
			 * Creates an instance of SVNRepository to work with the repository.
			 * All user's requests to the repository are relative to the
			 * repository location used to create this SVNRepository. SVNURL is
			 * a wrapper for URL strings that refer to repository locations.
			 */
			repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url));
		} catch (SVNException svne) {
			/*
			 * Perhaps a malformed URL is the cause of this exception
			 */
			logger.error("error while creating an SVNRepository for the location '" + url + "': " + svne.getMessage());
			return null;
		}

		/*
		 * User's authentication information (name/password) is provided via an
		 * ISVNAuthenticationManager instance. SVNWCUtil creates a default
		 * authentication manager given user's name and password.
		 * 
		 * Default authentication manager first attempts to use provided user
		 * name and password and then falls back to the credentials stored in
		 * the default Subversion credentials storage that is located in
		 * Subversion configuration area. If you'd like to use provided user
		 * name and password only you may use BasicAuthenticationManager class
		 * instead of default authentication manager:
		 * 
		 * authManager = new BasicAuthenticationsManager(userName,
		 * userPassword);
		 * 
		 * You may also skip this point - anonymous access will be used.
		 */
		ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(name, password);
		repository.setAuthenticationManager(authManager);

		/*
		 * This Map will be used to get the file properties. Each Map key is a
		 * property name and the value associated with the key is the property
		 * value.
		 */
		SVNProperties fileProperties = new SVNProperties();
		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		try {
			/*
			 * Checks up if the specified path really corresponds to a file. If
			 * doesn't the program exits. SVNNodeKind is that one who says what
			 * is located at a path in a revision. -1 means the latest revision.
			 */
			SVNNodeKind nodeKind = repository.checkPath(filePath, -1);

			if (nodeKind == SVNNodeKind.NONE) {
				logger.error("There is no entry at '" + url + "'.");
				return null;
			} else if (nodeKind == SVNNodeKind.DIR) {
				logger.error("The entry at '" + url + "' is a directory while a file was expected.");
				return null;
			}
			/*
			 * Gets the contents and properties of the file located at filePath
			 * in the repository at the latest revision (which is meant by a
			 * negative revision number).
			 */
			repository.getFile(filePath, -1, fileProperties, baos);

		} catch (SVNException svne) {
			logger.error("error while fetching the file contents and properties: " + svne.getMessage());
			return null;
		}

		/*
		 * Here the SVNProperty class is used to get the value of the
		 * svn:mime-type property (if any). SVNProperty is used to facilitate
		 * the work with versioned properties.
		 */
		String mimeType = fileProperties.getStringValue(SVNProperty.MIME_TYPE);

		/*
		 * SVNProperty.isTextMimeType(..) method checks up the value of the
		 * mime-type file property and says if the file is a text (true) or not
		 * (false).
		 */
		boolean isTextType = SVNProperty.isTextMimeType(mimeType);

		/*
		 * Displays the file contents in the console if the file is a text.
		 */
		if (isTextType) {
			logger.debug("File contents: " + baos.toString());
			return baos.toString();
		} else {
			logger.error("File contents can not be displayed in the console since the mime-type property says that it's not a kind of a text file.");
			return null;
		}
	}

	/*
	 * Initializes the library to work with a repository via different
	 * protocols.
	 */
	private static void setupLibrary() {
		/*
		 * For using over http:// and https://
		 */
		DAVRepositoryFactory.setup();
		/*
		 * For using over svn:// and svn+xxx://
		 */
		SVNRepositoryFactoryImpl.setup();

		/*
		 * For using over file:///
		 */
		FSRepositoryFactory.setup();
	}
}
